<template>
  <vxe-select
      ref="selectRef"
      :="$attrs"
      clearable
      v-model="selectValue"
      :options="optionData"
      @clear="clearClick"
      @change="change"
      :filterable="isSearch"
  >
  </vxe-select>
</template>


<script setup>
import {nextTick, onMounted, ref, watch, watchEffect} from "vue";
import {getDistData} from "@/api/api-dist";
import {useNamespace} from "element-plus";

let ns = useNamespace("select", ref('rk'));


const emits = defineEmits(['change', 'update:modelValue'])


const props = defineProps({
  modelValue: {
    type: [Object, String, Number]
  },
  /**
   * label字段指定 默认和el-select默认字段相同
   */
  labelConfig: {
    type: Object,
    default: () => {
      return {
        value: "value",
        label: "label"
      }
    }
  },
  options: {
    type: Array,
  },
  /**
   * 服务器请求方法 返回数组参数
   */
  server: {
    type: Function,
  },
  showCode: {
    type: Boolean,
    default: true
  },
  /**
   * 字典项根据字典值查询，Object:{name:'XM_OBJ_NAME',params:{},dataLabel:'data'}
   */
  dist: {
    type: [String, Object],
    default: ""
  },
  isSearch: {
    type: Boolean,
    default: true
  }
})

const selectRef = ref(null)

const selectValue = ref("")

watch(selectValue, (v) => {
  emits('update:modelValue', v)
})
watchEffect(() => {
  selectValue.value = props.modelValue
})
const optionData = ref([])

//优先级options>dist>server
const parserOptionsData = () => {
  /**
   * 判断传入值
   */
  if (props.options) {
    propOptionsType()
  } else if (props.dist) {
    propDistType()
  } else if (props.server) {
    propServerType()
  }
}

/**
 * 生成 dataOption的值（赋值）
 * @param options
 */
const generateDataOptions = (options) => {
  if (options && Array.isArray(options)) {
    let data = options.map(item => {
      let temp = {
        value: item[props.labelConfig.value],
        label: ""
      }
      if (props.labelConfig) {
        if (typeof props.labelConfig.label === 'function') {
          if (props.showCode && item['code']) {
            temp.label = `${item['code']} ${props.labelConfig.label(item)}`
          } else {
            temp.label = props.labelConfig.label(item)
          }
        } else {
          if (props.showCode && item['code']) {
            temp.label = `${item['code']} ${item[props.labelConfig.label]}`
          } else {
            temp.label = item[props.labelConfig.label]
          }
        }
      }
      return temp
    })
    optionData.value = data
  }
}

/**
 * 数据是Option处理
 */
const propOptionsType = () => {
  if (props.options && Array.isArray(props.options)) {
    generateDataOptions(props.options)
  }
}
/**
 * 数据是Dist
 * @returns {Promise<void>}
 */
const propDistType = async () => {
  let options = []
  if (props.dist) {
    let params = {}
    let dataLabel = 'data'
    if (typeof props.dist === 'string') {
      params = {name: props.dist}
    } else if (typeof props.dist === 'object') {

      if (props.dist.hasOwnProperty('name' && props.dist['name'])) {
        Object.assign(params, {name: props.dist['name']})
      }
      if (props.dist.hasOwnProperty('params') && props.dist['params']) {
        Object.assign(params, props.dist[params])
      }
      if (props.dist.hasOwnProperty('dataLabel') && props.dist['dataLabel']) {
        dataLabel = props.dist['dataLabel']
      }
    }
    let resp = await getDistData(params)
    options = resp[dataLabel]
  }
  generateDataOptions(options)
}

/**
 * 数据是Option处理
 */
const propServerType = async () => {
  let option = await props.server()
  generateDataOptions(option)
}

const change = (value) => {
  let data = optionData.value.filter(item => {
    return item[props.labelConfig.value] === value
  })
  emits('change', data, value)
}
onMounted(() => {
  nextTick(() => {
    parserOptionsData()
  })
})


const clearClick = () => {
  emits('change', null, '')
}


</script>

<style scoped lang="scss">
@import "../../styles/public/pub-bem";

@include b('select') {
  &-option {
    &__input {
      position: absolute;
      z-index: 1000;
      margin: 0;
      padding: 0;
      width: 100%;
      top: 0;
      background-color: #ffffff
    }
  }
}
</style>
